#pragma once
#include "Includes.h"
#include "GameClasses.h"


class CTraceFilterSkipTwoEntities
{
public:
	CTraceFilterSkipTwoEntities(void *pPassEnt1, void *pPassEnt2)
	{
		m_pPassEnt1 = pPassEnt1;
		m_pPassEnt2 = pPassEnt2;
	}

	virtual bool ShouldHitEntity(void *pHandleEntity, int contentsMask)
	{
		return !(pHandleEntity == m_pPassEnt1 || pHandleEntity == m_pPassEnt2);
	}

	virtual int GetTraceType() const
	{
		return 0;
	}

	void *m_pPassEnt1;
	void *m_pPassEnt2;
};

class CBaseTrace
{
public:

	bool IsDispSurface( void )				{ return ( ( dispFlags & DISPSURF_FLAG_SURFACE ) != 0 ); }
	bool IsDispSurfaceWalkable( void )		{ return ( ( dispFlags & DISPSURF_FLAG_WALKABLE ) != 0 ); }
	bool IsDispSurfaceBuildable( void )		{ return ( ( dispFlags & DISPSURF_FLAG_BUILDABLE ) != 0 ); }
	bool IsDispSurfaceProp1( void )			{ return ( ( dispFlags & DISPSURF_FLAG_SURFPROP1 ) != 0 ); }
	bool IsDispSurfaceProp2( void )			{ return ( ( dispFlags & DISPSURF_FLAG_SURFPROP2 ) != 0 ); }

	inline Entity** HitEntity() { return MakePointerGEN< Entity* >( this, 0x4C ); }

public:
	SD_Tools::Vector			startpos;				// start position
	SD_Tools::Vector			endpos;					// final position
	cplane_t					plane;					// surface normal at impact

	float						fraction;				// time completed, 1.0 = didn't hit anything

	int							contents;				// contents on other side of surface hit
	unsigned short				dispFlags;				// displacement flags for marking surfaces with data

	bool						allsolid;				// if true, plane is not valid
	bool						startsolid;				// if true, the initial point was in a solid area

	CBaseTrace() {}
};

class CGameTrace : public CBaseTrace
{
public:

	// Returns true if hEnt points at the world entity.
	// If this returns true, then you can't use GetHitBoxIndex().
	bool DidHitWorld() const;

	// Returns true if we hit something and it wasn't the world.
	bool DidHitNonWorldEntity() const;

	// Gets the entity's network index if the trace has hit an entity.
	// If not, returns -1.
	int GetEntityIndex() const;

	// Returns true if there was any kind of impact at all
	bool DidHit() const;

	// The engine doesn't know what a CBaseEntity is, so it has a backdoor to 
	// let it get at the edict.


public:

	float		fractionleftsolid;		// time we left a solid, only valid if we started in solid
	csurface_t	surface;				// surface hit (impact surface)

	int			hitgroup;				// 0 == generic, non-zero is specific body part
	short		physicsbone;			// physics bone hit by trace in studio


	Entity		*m_pEnt;

	// NOTE: this member is overloaded.
	// If hEnt points at the world entity, then this is the static prop index.
	// Otherwise, this is the hitbox index.
	int			hitbox;					// box hit by trace in studio

	CGameTrace() {}

};